package com.alibaba.algo.apiimpl.policy;

import com.alibaba.algo.cooperation.feign.vo.res.UserRoleInfoResVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.SelectResourceListByRoleReqVO;
import com.alibaba.algo.core.exception.BaseException;
import com.alibaba.algo.domain.app.FunctionInfoDomain;
import com.alibaba.algo.domain.user.SysAppDomain;
import com.alibaba.algo.domain.user.SysRoleResourceDomain;
import com.alibaba.algo.domain.user.SysUserRoleDomain;
import com.alibaba.algo.dtos.user.SysResourceTreeNodeDTO;
import com.alibaba.algo.entity.user.SysApp;
import com.alibaba.algo.exception.SysPolicyErrorCode;
import com.alibaba.fastjson.JSON;
import com.aliyun.gsuite.request.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class SysPolicyServiceImpl implements SysPolicyService {
    private static final String DEFAULT_FUNCTION_NAME = "YUNQIAO_DEFAULT_FUNCTION";
    private static final String DEFAULT_CREATE_NAME = "DEFAULT_CREATE_NAME";
    private static final Long DEFAULT_APP_ACOUNT_ID = 0L;

    @Autowired
    FunctionInfoDomain functionInfoDomain;

    @Autowired
    private SysUserRoleDomain sysUserRoleDomain;

    @Autowired
    private SysAppDomain sysAppDomain;

    @Autowired
    private SysRoleResourceDomain sysRoleResourceDomain;


    @Override
    public Map<String, Boolean> batchCheckPolicy(BatchCheckPolicyVO batchCheckPolicyVO) {
        if (batchCheckPolicyVO.getAppId() == null || batchCheckPolicyVO.getPolicies() == null || batchCheckPolicyVO.getPolicies().isEmpty() || batchCheckPolicyVO.getUserId() == null) {
            throw new BaseException(SysPolicyErrorCode.paramsInvalid.getCode(), SysPolicyErrorCode.paramsInvalid.getMessage() + ": " + String.format("params [appId, policyCode, userId] not allowed empty, caller params [%s, %s, %s]", batchCheckPolicyVO.getAppId(), batchCheckPolicyVO.getPolicies() != null ? JSON.toJSONString(batchCheckPolicyVO.getPolicies()) : null, batchCheckPolicyVO.getUserId()));
        }

        Map<String, Boolean> filters = new HashMap<>();
        List<Long> roleIds = listRoleIds(batchCheckPolicyVO.getUserId());
        if (roleIds.isEmpty()) {
            return null;
        }
        List<SysResourceTreeNodeDTO> resourceNodeList  = listResourceNodes(batchCheckPolicyVO.getAppId(), roleIds);
        if (resourceNodeList == null) {
            return null;
        }

        for (PolicyVO policyVO : batchCheckPolicyVO.getPolicies()) {
            boolean isExist = false;
            for (SysResourceTreeNodeDTO resourceNode : resourceNodeList) {
                if (policyVO.getPolicyCode().equals(resourceNode.getResourceCode())) {
                    isExist = true;
                    break;
                }
            }
            filters.put(policyVO.getPolicyCode() + ":" + policyVO.getPolicyType(), isExist);
        }
        return filters;
    }

    @Override
    public boolean checkPolicy(CheckPolicyVO checkPolicyVO) {
        if (checkPolicyVO.getAppId() == null || checkPolicyVO.getPolicyCode() == null || checkPolicyVO.getUserId() == null) {
            throw new BaseException(SysPolicyErrorCode.paramsInvalid.getCode(), SysPolicyErrorCode.paramsInvalid.getMessage() + ": " + String.format("params [appId, policyCode, userId] not allowed empty, caller params [%s, %s, %s]", checkPolicyVO.getAppId(), checkPolicyVO.getPolicyCode(), checkPolicyVO.getUserId()));
        }

        List<Long> roleIds = listRoleIds(checkPolicyVO.getUserId());
        if (roleIds.size() == 0) {
            return false;
        }
        List<SysResourceTreeNodeDTO> resourceNodeList  = listResourceNodes(checkPolicyVO.getAppId(), roleIds);
        if (resourceNodeList == null) {
            return false;
        }
        for (SysResourceTreeNodeDTO resourceNode : resourceNodeList) {
            if (checkPolicyVO.getPolicyCode().equals(resourceNode.getResourceCode())) {
                return true;
            }
        }

        return false;
    }


    private List<Long> listRoleIds(String userId) {
        List<UserRoleInfoResVO> roleUserInfoResList = sysUserRoleDomain.selectRoleListByUserId(Long.valueOf(userId), null,null);
        List<Long> roleIds = new ArrayList<>();
        for (UserRoleInfoResVO roleInfo : roleUserInfoResList) {
            roleIds.add(roleInfo.getRoleId());
        }
        return roleIds;
    }
    private List<SysResourceTreeNodeDTO> listResourceNodes(String appId, List<Long> roleIds) {
        SysApp sysApp = sysAppDomain.getById(Long.valueOf(appId));
        if (sysApp == null) {
            throw new BaseException(SysPolicyErrorCode.appNotExist.getCode(), SysPolicyErrorCode.appNotExist.getMessage());
        }

        SelectResourceListByRoleReqVO req = new SelectResourceListByRoleReqVO();
        req.setAppCode(sysApp.getAppCode());
        req.setRoleIdList(roleIds);
        return sysRoleResourceDomain.selectResourceListByRoleIdListAndAppCode(req);
    }

}
